package main

import (
	"bufio"
	"bytes"
	"database/sql"
	"log"
	"os"
	"reflect"
	"strconv"

	"test.com/fusion"
	"test.com/worlddb"
)

var worldDB *sql.DB
var dbFile *os.File

type dbTable struct {
	i      interface{}
	buffer *bytes.Buffer
}

var dbTables = []dbTable{
	{(*worlddb.CharPrototype)(nil), nil},
	{(*worlddb.Configure)(nil), nil},
	// {(*worlddb.CreatureAttribute)(nil), nil},
	// {(*worlddb.CreatureSpawn)(nil), nil},
	{(*worlddb.GameTime)(nil), nil},
	{(*worlddb.ItemEquipPrototype)(nil), nil},
	{(*worlddb.ItemPrototype)(nil), nil},
	{(*worlddb.LandmarkPoint)(nil), nil},
	// {(*worlddb.LootSet)(nil), nil},
	// {(*worlddb.LootSetGroup)(nil), nil},
	// {(*worlddb.LootSetGroupCheque)(nil), nil},
	// {(*worlddb.LootSetGroupItem)(nil), nil},
	// {(*worlddb.MapGraveyard)(nil), nil},
	{(*worlddb.MapInfo)(nil), nil},
	{(*worlddb.MapZone)(nil), nil},
	{(*worlddb.PayShop)(nil), nil},
	// {(*worlddb.PlayerAttribute)(nil), nil},
	{(*worlddb.PlayerBase)(nil), nil},
	// {(*worlddb.QuestCreatureVisible)(nil), nil},
	{(*worlddb.QuestPrototype)(nil), nil},
	{(*worlddb.QuestQuestion)(nil), nil},
	// {(*worlddb.Scriptable)(nil), nil},
	{(*worlddb.ShopPrototype)(nil), nil},
	{(*worlddb.SObjPrototype)(nil), nil},
	{(*worlddb.SpellInfo)(nil), nil},
	{(*worlddb.SpellLevelEffectInfo)(nil), nil},
	{(*worlddb.SpellLevelInfo)(nil), nil},
	// {(*worlddb.StaticObjectSpawn)(nil), nil},
	{(*worlddb.String_text_list)(nil), nil},
	// {(*worlddb.TeleportPoint)(nil), nil},
	// {(*worlddb.WayPoint)(nil), nil},
}

func main() {
	if len(os.Args) != 7 {
		log.Fatalf("%s: host port user password database dbfile", os.Args[0])
	}
	initMysql(os.Args[1], os.Args[2], os.Args[3], os.Args[4], os.Args[5])
	defer worldDB.Close()
	initDBFile(os.Args[6])
	defer dbFile.Close()
	db2File()
}

func initMysql(host, port, user, password, database string) {
	worldDB = fusion.OpenMysql(&fusion.MysqlConfig{
		Host:     host,
		Port:     uint16(fusion.Check(strconv.Atoi(port))[0].(int)),
		User:     user,
		Password: password,
		Database: database,
	}, 1, 1)
}

func initDBFile(dbfile string) {
	dbFile = fusion.Check(os.Create(dbfile))[0].(*os.File)
}

func db2File() {
	for i, dbTable := range dbTables {
		dbTables[i].buffer = loadDBTable(reflect.TypeOf(dbTable.i))
	}
	w := bufio.NewWriter(dbFile)
	for _, dbTable := range dbTables {
		tableName := dbTable.i.(fusion.IGetTableName).GetTableName()
		w.WriteByte(byte(len(tableName)))
		w.WriteString(tableName)
		fusion.ToWriter7BitEncodedInt(uint(dbTable.buffer.Len()), w)
	}
	w.WriteByte(0)
	for _, dbTable := range dbTables {
		w.Write(dbTable.buffer.Bytes())
	}
	w.Flush()
}

func loadDBTable(t reflect.Type) *bytes.Buffer {
	tblVals, err := fusion.LoadJsontableFromDB(worldDB, t, "")
	if err != nil {
		log.Fatal(err)
	}
	buffer := &bytes.Buffer{}
	for i, n := 0, tblVals.Len(); i < n; i++ {
		err := fusion.MarshalEntityToWriter(tblVals.Index(i).Interface(), buffer)
		if err != nil {
			log.Fatal(err)
		}
	}
	return buffer
}
